<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>一次性实时聊天室</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
    <!-- 其他头部信息 -->
    <link rel="icon" href="https://picsum.photos/32/32" type="image/png">
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#3B82F6',
                        secondary: '#64748B',
                        success: '#10B981',
                        warning: '#F59E0B',
                        danger: '#EF4444',
                        dark: '#1E293B',
                        light: '#F8FAFC',
                        chatbg: '#F1F5F9',
                        chatmsg: '#E2E8F0',
                        private: '#E0F2FE' // 私信消息背景色
                    },
                    fontFamily: {
                        inter: ['Inter', 'sans-serif'],
                    },
                }
            }
        }
    </script>
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .scrollbar-hide {
                -ms-overflow-style: none;
                scrollbar-width: none;
            }
            .scrollbar-hide::-webkit-scrollbar {
                display: none;
            }
            .message-appear {
                animation: fadeIn 0.3s ease-in-out;
            }
            @keyframes fadeIn {
                from { opacity: 0; transform: translateY(10px); }
                to { opacity: 1; transform: translateY(0); }
            }
            /* Emoji选择器样式 */
            .emoji-picker {
                position: absolute;
                bottom: calc(100% + 10px);
                left: 0;
                background: white;
                border-radius: 8px;
                box-shadow: 0 4px 12px rgba(0,0,0,0.15);
                width: 280px;
                max-height: 250px;
                overflow-y: auto;
                z-index: 100;
                transform-origin: bottom left;
                transform: scale(0.95);
                opacity: 0;
                pointer-events: none;
                transition: all 0.2s ease;
            }
            .emoji-picker.active {
                transform: scale(1);
                opacity: 1;
                pointer-events: all;
            }
            .emoji-category {
                padding: 8px 12px;
                border-bottom: 1px solid #eee;
            }
            .emoji-category-title {
                font-size: 12px;
                font-weight: 600;
                color: #666;
                margin-bottom: 8px;
            }
            .emoji-grid {
                display: grid;
                grid-template-columns: repeat(7, 1fr);
                gap: 5px;
            }
            .emoji-item {
                width: 32px;
                height: 32px;
                display: flex;
                align-items: center;
                justify-content: center;
                font-size: 18px;
                cursor: pointer;
                border-radius: 4px;
                transition: background 0.2s;
            }
            .emoji-item:hover {
                background: #f0f0f0;
            }
            .emoji-tabs {
                display: flex;
                border-bottom: 1px solid #eee;
                padding: 0 10px;
                overflow-x: auto;
                scrollbar-width: none;
            }
            .emoji-tabs::-webkit-scrollbar {
                display: none;
            }
            .emoji-tab {
                padding: 8px 12px;
                font-size: 14px;
                cursor: pointer;
                border-bottom: 2px solid transparent;
                transition: all 0.2s;
            }
            .emoji-tab.active {
                border-bottom-color: #3B82F6;
                color: #3B82F6;
                font-weight: 500;
            }
            .emoji-search {
                padding: 8px 12px;
                border-bottom: 1px solid #eee;
            }
            .emoji-search input {
                width: 100%;
                padding: 6px 10px;
                border: 1px solid #ddd;
                border-radius: 4px;
                font-size: 13px;
            }
            .emoji-trigger {
                position: relative;
            }
            /* 图片消息样式 */
            .message-image {
                max-width: 200px;
                max-height: 200px;
                border-radius: 6px;
                object-fit: cover;
                cursor: pointer;
                transition: transform 0.2s;
            }
            .message-image:hover {
                transform: scale(1.02);
            }
            /* 图片预览和上传样式 */
            .image-preview-container {
                position: relative;
                margin-bottom: 10px;
                border-radius: 8px;
                overflow: hidden;
                border: 1px solid #e2e8f0;
            }
            .image-preview {
                width: 100%;
                max-height: 200px;
                object-fit: contain;
                background-color: #f8fafc;
            }
            .remove-image {
                position: absolute;
                top: 5px;
                right: 5px;
                background-color: rgba(255,255,255,0.8);
                border-radius: 50%;
                width: 24px;
                height: 24px;
                display: flex;
                align-items: center;
                justify-content: center;
                cursor: pointer;
                font-size: 14px;
                color: #ef4444;
                transition: background-color 0.2s;
            }
            .remove-image:hover {
                background-color: white;
            }
            .upload-progress {
                height: 3px;
                background-color: #e2e8f0;
                position: absolute;
                bottom: 0;
                left: 0;
                width: 0%;
                background-color: #3b82f6;
                transition: width 0.3s ease;
            }
            /* 图片查看器 */
            .image-viewer {
                position: fixed;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                background-color: rgba(0,0,0,0.9);
                display: flex;
                align-items: center;
                justify-content: center;
                z-index: 1000;
                opacity: 0;
                pointer-events: none;
                transition: opacity 0.3s ease;
            }
            .image-viewer.active {
                opacity: 1;
                pointer-events: all;
            }
            .viewer-image {
                max-width: 90%;
                max-height: 90%;
                object-fit: contain;
            }
            .close-viewer {
                position: absolute;
                top: 20px;
                right: 20px;
                color: white;
                font-size: 24px;
                cursor: pointer;
            }
            /* 语音输入样式 */
            .voice-recording {
                animation: pulse 1.5s infinite;
            }
            @keyframes pulse {
                0% { transform: scale(1); background-color: rgba(239, 68, 68, 0.7); }
                50% { transform: scale(1.1); background-color: rgba(239, 68, 68, 1); }
                100% { transform: scale(1); background-color: rgba(239, 68, 68, 0.7); }
            }
            .voice-status {
                position: absolute;
                bottom: 70px;
                left: 50%;
                transform: translateX(-50%);
                background-color: rgba(0, 0, 0, 0.7);
                color: white;
                padding: 8px 16px;
                border-radius: 20px;
                font-size: 14px;
                z-index: 50;
                display: none;
            }
            .voice-status.active {
                display: block;
            }
            .voice-levels {
                display: flex;
                align-items: center;
                justify-content: center;
                gap: 3px;
                margin-top: 8px;
            }
            .voice-level {
                width: 3px;
                background-color: white;
                border-radius: 3px;
                animation: level 1s infinite;
            }
            @keyframes level {
                0%, 100% { height: 8px; }
                50% { height: 16px; }
            }
            /* 私信相关样式 */
            .chat-tabs {
                display: flex;
                border-bottom: 1px solid #e2e8f0;
            }
            .chat-tab {
                padding: 10px 16px;
                cursor: pointer;
                border-bottom: 2px solid transparent;
                font-weight: 500;
                transition: all 0.2s;
            }
            .chat-tab.active {
                border-bottom-color: #3B82F6;
                color: #3B82F6;
            }
            .private-chat-container {
                display: none;
                flex-direction: column;
                height: 100%;
            }
            .private-chat-container.active {
                display: flex;
            }
            .private-chat-header {
                padding: 12px 16px;
                border-bottom: 1px solid #e2e8f0;
                display: flex;
                align-items: center;
            }
            .private-chat-avatar {
                width: 36px;
                height: 36px;
                border-radius: 50%;
                object-fit: cover;
                margin-right: 12px;
            }
            .private-chat-name {
                font-weight: 500;
            }
            .private-messages {
                flex-grow: 1;
                padding: 16px;
                overflow-y: auto;
                background-color: #f8fafc;
            }
            .private-input-area {
                padding: 12px 16px;
                border-top: 1px solid #e2e8f0;
                background-color: white;
            }
            .private-chat-list {
                padding: 16px;
                overflow-y: auto;
            }
            .private-chat-item {
                padding: 10px 12px;
                border-radius: 8px;
                margin-bottom: 8px;
                cursor: pointer;
                transition: background-color 0.2s;
                display: flex;
                align-items: center;
            }
            .private-chat-item:hover {
                background-color: #f1f5f9;
            }
            .private-chat-item.unread {
                background-color: #eff6ff;
            }
            .unread-badge {
                background-color: #3B82F6;
                color: white;
                border-radius: 50%;
                width: 18px;
                height: 18px;
                display: flex;
                align-items: center;
                justify-content: center;
                font-size: 10px;
                margin-left: auto;
            }
            .back-to-public {
                margin-right: 12px;
                cursor: pointer;
                color: #64748B;
            }
            .back-to-public:hover {
                color: #3B82F6;
            }
        }
    </style>
</head>
<body class="font-inter bg-gray-100 min-h-screen flex flex-col">
<header class="bg-white shadow-sm py-4 px-6 sticky top-0 z-10">
    <div class="container mx-auto flex justify-between items-center">
        <h1 class="text-xl font-bold text-dark flex items-center">
            <i class="fa fa-comments-o text-primary mr-2"></i>
            一次性实时聊天室
        </h1>
        <div class="flex items-center">
            <button id="themeToggle" class="p-2 rounded-full hover:bg-gray-100 transition-colors">
                <i class="fa fa-moon-o text-gray-600"></i>
            </button>
            <div id="connectionStatus" class="ml-4 flex items-center">
                <span id="statusIndicator" class="w-2 h-2 rounded-full bg-gray-400 mr-2"></span>
                <span id="statusText" class="text-sm text-gray-600">未连接</span>
            </div>
        </div>
    </div>
</header>

<main class="flex-grow container mx-auto p-4 md:p-6">
    <div class="max-w-4xl mx-auto bg-white rounded-xl shadow-lg overflow-hidden h-[calc(100vh-12rem)] flex flex-col">
        <!-- 聊天头部 -->
        <div class="p-4 border-b border-gray-200 flex justify-between items-center">
            <div class="flex items-center">
                <div class="relative">
                    <img src="https://picsum.photos/40/40" alt="聊天室头像" class="w-10 h-10 rounded-full object-cover">
                    <span class="absolute bottom-0 right-0 w-3 h-3 bg-success rounded-full border-2 border-white"></span>
                </div>
                <div class="ml-3">
                    <h2 class="font-bold text-dark">公共聊天室</h2>
                    <p class="text-xs text-gray-500">多人实时聊天</p>
                </div>
            </div>
            <div class="flex space-x-2">
                <button id="toggleUsers" class="p-2 rounded-full hover:bg-gray-100 transition-colors">
                    <i class="fa fa-users text-gray-600"></i>
                </button>
                <button id="settingsBtn" class="p-2 rounded-full hover:bg-gray-100 transition-colors">
                    <i class="fa fa-cog text-gray-600"></i>
                </button>
            </div>
        </div>

        <!-- 聊天内容区 -->
        <div class="flex-grow flex overflow-hidden">
            <!-- 在线用户列表 -->
            <div id="userList" class="w-64 bg-gray-50 border-r border-gray-200 hidden md:block transform -translate-x-full transition-transform duration-300 ease-in-out fixed md:relative h-[calc(100vh-12rem-56px)] z-10 md:z-auto">
                <div class="p-4 border-b border-gray-200">
                    <h3 class="font-bold text-dark">在线用户</h3>
                    <div class="relative mt-2">
                        <input type="text" placeholder="搜索用户..." class="w-full pl-8 pr-4 py-2 rounded-lg border border-gray-300 focus:ring-2 focus:ring-primary/50 focus:border-primary outline-none text-sm">
                        <i class="fa fa-search absolute left-3 top-1/2 -translate-y-1/2 text-gray-400"></i>
                    </div>
                </div>
                <div class="overflow-y-auto h-[calc(100%-100px)] scrollbar-hide p-2">
                    <div id="usersContainer" class="space-y-2">
                        <!-- 用户列表将通过JS动态生成 -->
                    </div>
                </div>
            </div>

            <!-- 遮罩层 -->
            <div id="userListOverlay" class="fixed inset-0 bg-black/50 z-5 hidden md:hidden"></div>

            <!-- 消息内容区 -->
            <div class="flex-grow flex flex-col bg-chatbg">
                <!-- 聊天标签切换 -->
                <div class="chat-tabs">
                    <div id="publicChatTab" class="chat-tab active" data-tab="public">公共聊天</div>
                    <div id="privateChatsTab" class="chat-tab" data-tab="privateList">私信列表</div>
                </div>

                <!-- 公共聊天区域 -->
                <div id="publicChatContainer" class="flex-grow flex flex-col">
                    <div id="messageContainer" class="flex-grow p-4 overflow-y-auto scrollbar-hide">
                        <div class="text-center my-4">
                            <span class="bg-gray-200 text-gray-500 text-xs px-3 py-1 rounded-full" id="loginTime"></span>
                        </div>

                        <!-- 系统消息 -->
                        <div class="text-center my-2 message-appear">
                            <span class="bg-gray-200 text-gray-600 text-xs px-3 py-1 rounded-full">系统消息：欢迎加入聊天室</span>
                        </div>

                        <!-- 消息将通过JS动态生成 -->
                    </div>

                    <!-- 公共聊天输入区域 -->
                    <div class="p-4 border-t border-gray-200 relative">
                        <!-- 语音状态提示 -->
                        <div id="voiceStatus" class="voice-status">
                            <div>正在录音...</div>
                            <div class="voice-levels">
                                <div class="voice-level" style="animation-delay: 0s"></div>
                                <div class="voice-level" style="animation-delay: 0.2s"></div>
                                <div class="voice-level" style="animation-delay: 0.4s"></div>
                                <div class="voice-level" style="animation-delay: 0.6s"></div>
                                <div class="voice-level" style="animation-delay: 0.8s"></div>
                            </div>
                        </div>

                        <!-- 图片预览区域 -->
                        <div id="imagePreviewContainer" class="image-preview-container hidden">
                            <img id="imagePreview" class="image-preview" src="" alt="图片预览">
                            <div id="removeImage" class="remove-image">
                                <i class="fa fa-times"></i>
                            </div>
                            <div id="uploadProgress" class="upload-progress"></div>
                        </div>

                        <div class="flex space-x-2 mb-2">
                            <div class="emoji-trigger">
                                <button id="toggleEmojiPicker" class="p-2 rounded-full hover:bg-gray-100 transition-colors">
                                    <i class="fa fa-smile-o text-gray-600"></i>
                                </button>
                                <!-- Emoji选择器 -->
                                <div id="emojiPicker" class="emoji-picker">
                                    <div class="emoji-search">
                                        <input type="text" id="emojiSearch" placeholder="搜索表情...">
                                    </div>
                                    <div class="emoji-tabs">
                                        <div class="emoji-tab active" data-category="all">全部</div>
                                        <div class="emoji-tab" data-category="people">表情</div>
                                        <div class="emoji-tab" data-category="nature">自然</div>
                                        <div class="emoji-tab" data-category="food">食物</div>
                                        <div class="emoji-tab" data-category="activities">活动</div>
                                        <div class="emoji-tab" data-category="travel">旅行</div>
                                        <div class="emoji-tab" data-category="objects">物品</div>
                                        <div class="emoji-tab" data-category="symbols">符号</div>
                                        <div class="emoji-tab" data-category="flags">旗帜</div>
                                    </div>
                                    <div id="emojiContent" class="emoji-content p-2">
                                        <!-- Emoji内容将通过JS动态生成 -->
                                    </div>
                                </div>
                            </div>
                            <label class="cursor-pointer p-2 rounded-full hover:bg-gray-100 transition-colors">
                                <i class="fa fa-picture-o text-gray-600"></i>
                                <input type="file" id="imageUpload" accept="image/*" class="hidden">
                            </label>
                            <button class="p-2 rounded-full hover:bg-gray-100 transition-colors">
                                <i class="fa fa-file-o text-gray-600"></i>
                            </button>
                            <button id="voiceBtn" class="p-2 rounded-full hover:bg-gray-100 transition-colors">
                                <i class="fa fa-microphone text-gray-600"></i>
                            </button>
                        </div>
                        <div class="flex">
                            <input id="messageInput" type="text" placeholder="输入消息..." class="flex-grow px-4 py-2 rounded-l-lg border border-gray-300 focus:ring-2 focus:ring-primary/50 focus:border-primary outline-none">
                            <button id="sendBtn" class="bg-primary hover:bg-primary/90 text-white px-4 py-2 rounded-r-lg transition-colors">
                                发送
                            </button>
                        </div>
                    </div>
                </div>

                <!-- 私信列表区域 -->
                <div id="privateChatsListContainer" class="hidden flex-grow overflow-y-auto bg-white">
                    <div class="private-chat-list" id="privateChatsList">
                        <!-- 私信列表将通过JS动态生成 -->
                        <div class="text-center text-gray-500 py-8">
                            暂无私信，点击在线用户发送私信
                        </div>
                    </div>
                </div>

                <!-- 私信聊天区域 -->
                <div id="privateChatContainer" class="private-chat-container">
                    <div class="private-chat-header">
                        <div class="back-to-public" id="backToPrivateList">
                            <i class="fa fa-arrow-left"></i>
                        </div>
                        <img id="privateChatAvatar" src="" alt="用户头像" class="private-chat-avatar">
                        <div>
                            <div id="privateChatName" class="private-chat-name"></div>
                            <div class="text-xs text-gray-500">在线</div>
                        </div>
                    </div>

                    <div id="privateMessagesContainer" class="private-messages" style="height: 74%">
                        <!-- 私信消息将通过JS动态生成 -->
                    </div>

                    <div class="private-input-area">
                        <div class="flex space-x-2 mb-2">
                            <div class="emoji-trigger">
                                <button id="togglePrivateEmojiPicker" class="p-2 rounded-full hover:bg-gray-100 transition-colors">
                                    <i class="fa fa-smile-o text-gray-600"></i>
                                </button>
                                <!-- 私信Emoji选择器 -->
                                <div id="privateEmojiPicker" class="emoji-picker">
                                    <div class="emoji-search">
                                        <input type="text" id="privateEmojiSearch" placeholder="搜索表情...">
                                    </div>
                                    <div class="emoji-tabs">
                                        <div class="emoji-tab active" data-category="all">全部</div>
                                        <div class="emoji-tab" data-category="people">表情</div>
                                        <div class="emoji-tab" data-category="nature">自然</div>
                                        <div class="emoji-tab" data-category="food">食物</div>
                                        <div class="emoji-tab" data-category="activities">活动</div>
                                        <div class="emoji-tab" data-category="travel">旅行</div>
                                        <div class="emoji-tab" data-category="objects">物品</div>
                                        <div class="emoji-tab" data-category="symbols">符号</div>
                                        <div class="emoji-tab" data-category="flags">旗帜</div>
                                    </div>
                                    <div id="privateEmojiContent" class="emoji-content p-2">
                                        <!-- Emoji内容将通过JS动态生成 -->
                                    </div>
                                </div>
                            </div>
                            <label class="cursor-pointer p-2 rounded-full hover:bg-gray-100 transition-colors">
                                <i class="fa fa-picture-o text-gray-600"></i>
                                <input type="file" id="privateImageUpload" accept="image/*" class="hidden">
                            </label>
                            <button id="privateVoiceBtn" class="p-2 rounded-full hover:bg-gray-100 transition-colors">
                                <i class="fa fa-microphone text-gray-600"></i>
                            </button>
                        </div>
                        <div class="flex">
                            <input id="privateMessageInput" type="text" placeholder="输入私信..." class="flex-grow px-4 py-2 rounded-l-lg border border-gray-300 focus:ring-2 focus:ring-primary/50 focus:border-primary outline-none">
                            <button id="privateSendBtn" class="bg-primary hover:bg-primary/90 text-white px-4 py-2 rounded-r-lg transition-colors">
                                发送
                            </button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</main>

<!-- 图片查看器 -->
<div id="imageViewer" class="image-viewer">
    <img id="viewerImage" class="viewer-image" src="" alt="图片查看">
    <div id="closeViewer" class="close-viewer">
        <i class="fa fa-times"></i>
    </div>
</div>

<footer class="bg-dark text-white py-4 px-6">
    <div class="container mx-auto text-center text-sm text-gray-400">
        <p>cain做的一次性实时聊天 &copy; 2025</p>
    </div>
</footer>

<!-- 连接设置模态框 -->
<div id="connectionModal" class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 hidden">
    <div class="bg-white rounded-xl shadow-xl w-full max-w-md p-6 transform scale-95 opacity-0 transition-all duration-300" id="modalContent">
        <div class="flex justify-between items-center mb-4">
            <h3 class="text-xl font-bold text-dark">连接设置</h3>
            <button id="closeModal" class="text-gray-400 hover:text-gray-600">
                <i class="fa fa-times"></i>
            </button>
        </div>
        <div class="space-y-4">
            <div style="display: none">
                <label for="wsUrl" class="block text-sm font-medium text-gray-700 mb-1">连接地址</label>
                <input disabled type="text" id="wsUrl" value="wss://c793c825.natappfree.cc/websocket" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary/50 focus:border-primary outline-none">
            </div>
            <div>
                <label for="username" class="block text-sm font-medium text-gray-700 mb-1">用户名</label>
                <input type="text" id="username" value="游客" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary/50 focus:border-primary outline-none">
            </div>
            <div class="pt-2">
                <button id="connectBtn" class="w-full bg-primary hover:bg-primary/90 text-white py-2 rounded-lg transition-colors">
                    连接
                </button>
            </div>
        </div>
    </div>
</div>

<script>
    // 原始页面标题，用于消息提示功能
    const originalTitle = document.title;
    // 未读消息计数
    let unreadMessageCount = 0;
    // WebSocket连接核心优化：添加心跳、重连、状态管理相关变量
    let ws;
    let username = '游客';
    let pingInterval = null; // 心跳定时器
    let reconnectTimer = null; // 重连定时器
    const PING_INTERVAL = 30000; // 心跳间隔（30秒）
    const RECONNECT_INTERVAL = 1000; // 重连间隔（5秒）
    let is主动关闭 = false; // 标记是否主动关闭连接
    let selectedImage = null; // 选中的图片
    let selectedPrivateImage = null; // 选中的私信图片
    let recognition; // 语音识别对象
    let isRecording = false; // 是否正在录音

    // 私信相关变量
    let privateChats = {}; // 存储私信内容 { targetUser: { messages: [], unread: 0 } }
    let currentPrivateChat = null; // 当前正在聊天的用户

    // 消息队列控制
    let messageQueue = [];
    let isSending = false;
    const MAX_QUEUE_SIZE = 20; // 最大消息队列长度
    const SEND_DELAY = 100; // 消息发送间隔，控制发送速率

    // 常用Emoji列表，分类整理
    const emojis = {
        people: [
            '😀', '😁', '😂', '🤣', '😃', '😄', '😅', '😆', '😉', '😊',
            '🙂', '🙃', '😋', '😎', '😍', '😘', '🥰', '😗', '😙', '👍',
            '👎', '👊', '✊', '🤛', '🤜', '👏', '🙌', '👐', '🤝', '👍'
        ],
        nature: [
            '☀️', '🌤️', '⛅', '🌥️', '☁️', '🌧️', '⛈️', '🌩️', '⚡', '❄️',
            '☃️', '🌨️', '🌦️', '🌪️', '🌫️', '🌊', '🌅', '🌄', '🌠', '🌌',
            '🌙', '🌚', '🌝', '⭐', '🌟', '✨', '💫', '🌕', '🌔', '🌓',
            '🌒', '🌑', '🌱', '🌿', '☘️', '🍀', '🎋', '🎍'
        ],
        food: [
            '🍏', '🍎', '🍐', '🍊', '🍋', '🍌', '🍉', '🍇', '🍓', '🍒',
            '🍑', '🥭', '🍍', '🥥', '🥑', '🍅', '🥝', '🍆', '🥔', '🥕',
            '🌽', '🌶️', '🥒', '🥬', '🥦', '🧄', '🧅', '🍄', '🥜', '🌰',
            '🍞', '🥐', '🥖', '🧀', '🍳', '🥚', '🥞', '🧇', '🍖', '🍗'
        ],
        activities: [
            '⚽', '🏀', '🏈', '⚾', '🎾', '🏐', '🏉', '🎱', '🎳', '🏓',
            '🏸', '🥅', '⛳', '⛸️', '🎿', '🏂', '🏋️', '🤸', '🤼', '🥊',
            '🥋', '🎭', '🎨', '🎬', '🎤', '🎹', '🎻', '🥁', '🎷', '🎺',
            '🎸', '🎲', '🎯', '🎮', '🎰', '🎳', '🧩', '🎨', '🎭', '🎪'
        ],
        travel: [
            '🚗', '🚕', '🚙', '🚌', '🚎', '🏎️', '🚓', '🚑', '🚒', '🚐',
            '🚚', '🚛', '🚜', '🚲', '🛵', '🏍️', '🚨', '🚔', '🚍', '🚘',
            '🚝', '🚄', '🚅', '🚆', '🚇', '🚈', '🚂', '🚀', '✈️', '🛩️',
            '🚁', '🛳️', '⛵', '🚤', '🛶', '🏰', '🏯', '🏟️', '🎡', '🎢'
        ],
        objects: [
            '⌚', '📱', '📲', '💻', '⌨️', '🖥️', '🖨️', '🖱️', '💽', '💾',
            '💿', '📀', '📼', '📷', '📸', '📹', '🎥', '📞', '☎️', '📟',
            '📠', '🔋', '🔌', '💡', '🔦', '🕯️', '🪔', '🏮', '📔', '📕',
            '📖', '📗', '📘', '📙', '📚', '✏️', '✍️', '🖋️', '🖌️', '📝'
        ],
        symbols: [
            '❤️', '🧡', '💛', '💚', '💙', '💜', '🖤', '💔', '❣️', '💕',
            '💞', '💓', '💗', '💖', '💘', '💝', '💟', '🌟', '✨', '💫',
            '⚡', '🔥', '💥', '💢', '💦', '💧', '💨', '🍃', '🍂', '🍁',
            '🎊', '🎉', '🎎', '🎏', '🎐', '🎀', '🎁', '🎗️', '🏷️', '🔖'
        ],
        flags: [
            '🇨🇳', '🇺🇸', '🇬🇧', '🇯🇵', '🇰🇷', '🇫🇷', '🇩🇪', '🇮🇹', '🇷🇺', '🇨🇦',
            '🇦🇺', '🇧🇷', '🇮🇳', '🇷🇺', '🇨🇭', '🇸🇬', '🇭🇰', '🇲🇴', '🇹🇼', '🇫🇮',
            '🇸🇪', '🇳🇴', '🇩🇰', '🇮🇸', '🇬🇷', '🇪🇸', '🇵🇹', '🇳🇱', '🇧🇪', '🇦🇹'
        ]
    };

    // 生成所有表情的列表
    function getAllEmojis() {
        let all = [];
        for (const category in emojis) {
            all = [...all, ...emojis[category]];
        }
        return all;
    }

    // DOM元素
    const messageContainer = $('#messageContainer');
    const messageInput = $('#messageInput');
    const sendBtn = $('#sendBtn');
    const statusIndicator = $('#statusIndicator');
    const statusText = $('#statusText');
    const connectionModal = $('#connectionModal');
    const modalContent = $('#modalContent');
    const closeModal = $('#closeModal');
    const connectBtn = $('#connectBtn');
    const wsUrl = $('#wsUrl');
    const usernameInput = $('#username');
    const userList = $('#userList');
    const toggleUsers = $('#toggleUsers');
    const userListOverlay = $('#userListOverlay');
    const usersContainer = $('#usersContainer');
    const toggleEmojiPicker = $('#toggleEmojiPicker');
    const emojiPicker = $('#emojiPicker');
    const emojiContent = $('#emojiContent');
    const emojiSearch = $('#emojiSearch');
    const emojiTabs = $('.emoji-tab');
    const imageUpload = $('#imageUpload');
    const imagePreviewContainer = $('#imagePreviewContainer');
    const imagePreview = $('#imagePreview');
    const removeImage = $('#removeImage');
    const uploadProgress = $('#uploadProgress');
    const imageViewer = $('#imageViewer');
    const viewerImage = $('#viewerImage');
    const closeViewer = $('#closeViewer');
    const voiceBtn = $('#voiceBtn');
    const voiceStatus = $('#voiceStatus');

    // 私信相关DOM元素
    const publicChatTab = $('#publicChatTab');
    const privateChatsTab = $('#privateChatsTab');
    const publicChatContainer = $('#publicChatContainer');
    const privateChatsListContainer = $('#privateChatsListContainer');
    const privateChatContainer = $('#privateChatContainer');
    const privateChatsList = $('#privateChatsList');
    const backToPrivateList = $('#backToPrivateList');
    const privateChatAvatar = $('#privateChatAvatar');
    const privateChatName = $('#privateChatName');
    const privateMessagesContainer = $('#privateMessagesContainer');
    const privateMessageInput = $('#privateMessageInput');
    const privateSendBtn = $('#privateSendBtn');
    const togglePrivateEmojiPicker = $('#togglePrivateEmojiPicker');
    const privateEmojiPicker = $('#privateEmojiPicker');
    const privateEmojiContent = $('#privateEmojiContent');
    const privateEmojiSearch = $('#privateEmojiSearch');
    const privateImageUpload = $('#privateImageUpload');
    const privateVoiceBtn = $('#privateVoiceBtn');

    // 消息提示功能：显示未读消息提示
    function showUnreadMessagePrompt() {
        // 只有当页面不在视线内时才显示提示
        if (document.visibilityState === 'hidden' && unreadMessageCount > 0) {
            document.title = `(${unreadMessageCount}) 有新消息 - ${originalTitle}`;
        }
    }

    // 消息提示功能：重置未读消息计数
    function resetUnreadMessageCount() {
        unreadMessageCount = 0;
        document.title = originalTitle;
    }

    // 显示连接设置模态框
    function showConnectionModal() {
        connectionModal.removeClass('hidden');
        setTimeout(() => {
            modalContent.removeClass('scale-95 opacity-0').addClass('scale-100 opacity-100');
        }, 10);
    }

    // 隐藏连接设置模态框
    function hideConnectionModal() {
        modalContent.removeClass('scale-100 opacity-100').addClass('scale-95 opacity-0');
        setTimeout(() => {
            connectionModal.addClass('hidden');
        }, 300);
    }

    // 更新连接状态
    function updateConnectionStatus(isConnected) {
        if (isConnected) {
            statusIndicator.removeClass('bg-gray-400').addClass('bg-success');
            statusText.text('已连接');
        } else {
            statusIndicator.removeClass('bg-success').addClass('bg-gray-400');
            statusText.text('未连接');
        }
    }

    // 核心优化1：添加心跳机制
    function startHeartbeat() {
        // 清除旧定时器防止重复
        if (pingInterval) clearInterval(pingInterval);

        // 每30秒发送一次心跳消息
        pingInterval = setInterval(() => {
            if (ws && ws.readyState === WebSocket.OPEN) {
                sendMessage({
                    type: 'heartbeat',
                    timestamp: new Date().toISOString(),
                    action: 'ping'
                });
            }
        }, PING_INTERVAL);
    }

    // 核心优化2：自动重连逻辑
    function startReconnect() {
        // 清除旧定时器
        if (reconnectTimer) clearTimeout(reconnectTimer);

        // 如果是主动关闭则不重连
        if (is主动关闭){
            sendMessage({
                type: 'userList',
                username: username,
                timestamp: new Date().toISOString()
            });
            sendMessage({
                type: 'leave',
                username: username,
                timestamp: new Date().toISOString()
            });
            return;
        }

        // 5秒后尝试重连
        reconnectTimer = setTimeout(() => {
            const url = wsUrl.val().trim();
            if (url) {
                addSystemMessage('尝试重新连接服务器...');
                connectWebSocket(url);
            }
        }, RECONNECT_INTERVAL);
    }

    function generateUUID() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
            const r = crypto.getRandomValues(new Uint8Array(1))[0] % 16;
            const v = c === 'x' ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        });
    }

    // 连接WebSocket（核心优化）
    function connectWebSocket(url) {
        var item = localStorage.getItem("clientId");
        if(item == null){
            item = generateUUID();
            localStorage.setItem("clientId",item);
        }
        url = url+"/"+item;
        localStorage.setItem(item,username);
        // 清除现有连接
        if (ws && (ws.readyState === WebSocket.CONNECTING || ws.readyState === WebSocket.OPEN)) {
            is主动关闭 = true; // 标记为主动关闭
            sendMessage({
                type: 'userList',
                username: username,
                timestamp: new Date().toISOString()
            });
            sendMessage({
                type: 'leave',
                username: username,
                timestamp: new Date().toISOString()
            });
            ws.close(1000, '主动切换连接'); // 1000是正常关闭代码
        }

        try {
            ws = new WebSocket(url);
            is主动关闭 = false; // 重置主动关闭标记

            // 连接成功
            ws.onopen = function() {
                updateConnectionStatus(true);
                hideConnectionModal();
                // 清除重连定时器
                if (reconnectTimer) clearTimeout(reconnectTimer);

                // 启动心跳
                startHeartbeat();

                // 发送加入通知
                sendMessage({
                    type: 'userList',
                    username: username,
                    timestamp: new Date().toISOString()
                });
                sendMessage({
                    type: 'join',
                    username: username,
                    timestamp: new Date().toISOString()
                });
            };

            // 接收消息（增加心跳响应处理）
            ws.onmessage = function(event) {
                try {
                    const data = JSON.parse(event.data);
                    // 处理服务器返回的心跳响应
                    if (data.type === 'heartbeat' && data.action === 'pong') {
                        console.log('收到心跳响应，连接正常');
                        return;
                    }
                    // 原有消息处理逻辑
                    switch(data.type) {
                        case 'message':
                            // 只有非自己发送的消息才计数
                            if (!data.isSelf) {
                                unreadMessageCount++;
                                showUnreadMessagePrompt();
                            }
                            addMessage(data.username, data.message, data.timestamp, data.isSelf, data.image);
                            break;
                        case 'privateMessage':
                            // 私信消息处理
                            unreadMessageCount++;
                            showUnreadMessagePrompt();
                            addPrivateMessage(data.fromUser, data.toUser, data.message, data.timestamp, data.image);
                            break;
                        case 'system':
                            // 系统消息也计入未读提示
                            unreadMessageCount++;
                            showUnreadMessagePrompt();
                            addSystemMessage(data.message);
                            break;
                        case 'userList':
                            updateUserList(data.data);
                            break;
                        case 'join':
                            // 加入消息计入未读提示
                            unreadMessageCount++;
                            showUnreadMessagePrompt();
                            addSystemMessage(`${data.username}加入了聊天室`);
                            break;
                        case 'leave':
                            // 离开消息计入未读提示
                            unreadMessageCount++;
                            showUnreadMessagePrompt();
                            addSystemMessage(`${data.username}离开了聊天室`);
                            break;
                        // 处理分片消息
                        case 'largeMessageStart':
                        case 'largeMessageChunk':
                        case 'largeMessageEnd':
                            handleChunkedMessage(data);
                            break;
                    }
                } catch (error) {
                    // 不是JSON格式，作为普通文本消息处理
                    unreadMessageCount++;
                    showUnreadMessagePrompt();
                    addMessage('系统', event.data, new Date().toISOString(), false);
                }
            };

            // 核心优化3：关闭事件处理（增加重连触发）
            ws.onclose = function(event) {
                sendMessage({
                    type: 'userList',
                    username: username,
                    timestamp: new Date().toISOString()
                });
                sendMessage({
                    type: 'leave',
                    username: username,
                    timestamp: new Date().toISOString()
                });
                updateConnectionStatus(false);
                // 清除心跳定时器
                if (pingInterval) {
                    clearInterval(pingInterval);
                    pingInterval = null;
                }

                // 根据关闭代码判断原因
                const closeReason = {
                    1000: '正常关闭',
                    1001: '客户端离开页面',
                    1006: '意外断开连接',
                    1011: '服务器内部错误'
                };
                const reason = closeReason[event.code] || `未知错误（代码: ${event.code}）`;
                addSystemMessage(`连接已关闭: ${reason}`);

                // 触发重连（非主动关闭且非正常关闭时）
                if (event.code !== 1000 && event.code !== 1001) {
                    startReconnect();
                }
            };

            // 错误处理
            ws.onerror = function(error) {
                updateConnectionStatus(false);
                addSystemMessage(`连接发生错误: ${error.message || '未知错误'}`);
                startReconnect(); // 错误时触发重连
            };
        } catch (error) {
            updateConnectionStatus(false);
            addSystemMessage(`连接失败: ${error.message}`);
            startReconnect(); // 失败时触发重连
        }
    }

    // 消息队列处理
    function queueMessage(data) {
        // 队列满时移除最旧的消息
        if (messageQueue.length >= MAX_QUEUE_SIZE) {
            messageQueue.shift();
        }
        messageQueue.push(data);

        // 如果不在发送中，则开始发送
        if (!isSending) {
            processMessageQueue();
        }
    }

    // 处理消息队列，控制发送节奏
    function processMessageQueue() {
        if (messageQueue.length === 0) {
            isSending = false;
            return;
        }

        isSending = true;
        const data = messageQueue.shift();

        // 发送前检查连接状态
        if (ws && ws.readyState === WebSocket.OPEN) {
            try {
                // 对大消息进行压缩
                if (typeof data === 'string' && data.length > 1024) { // 大于1KB的消息进行压缩
                    const compressed = pako.deflate(data, { level: 5 });
                    const base64Data = btoa(String.fromCharCode.apply(null, compressed));
                    ws.send('COMPRESSED:' + base64Data);
                } else {
                    ws.send(data);
                }

                // 延迟发送下一条消息，避免带宽占用过高
                setTimeout(processMessageQueue, SEND_DELAY);
            } catch (error) {
                console.error('发送消息失败:', error);
                // 失败时重试一次
                messageQueue.unshift(data);
                setTimeout(processMessageQueue, 1000);
            }
        } else {
            // 连接不正常，1秒后重试
            messageQueue.unshift(data);
            setTimeout(processMessageQueue, 1000);
        }
    }

    // 发送消息
    function sendMessage(data) {
        if (ws && ws.readyState === WebSocket.OPEN) {
            queueMessage(JSON.stringify(data));
        } else {
            addSystemMessage('无法发送消息：未连接到服务器');
        }
    }

    // 发送私信
    function sendPrivateMessage(targetUser, message, image = null) {
        var item = localStorage.getItem("clientId");
        var userName=localStorage.getItem(item);
        if (!targetUser || targetUser.userid =="") {
            addSystemMessage('请选择要发送私信的用户');
            return;
        }
        const newFromUser = {
            "username":userName,
            "userid":item
        };

        const data = {
            type: 'privateMessage',
            fromUser: newFromUser,
            toUser: targetUser,
            message: message || '',
            timestamp: new Date().toISOString(),
            image: image || null
        };

        sendMessage(data);

        // 本地添加自己发送的私信
        if (!privateChats[newFromUser.userid]) {
            privateChats[newFromUser.userid] = {
                messages: [],
                unread: 0
            };
        }
        privateChats[newFromUser.userid].messages.push({
            fromUser: newFromUser,
            toUser: targetUser,
            message: message,
            timestamp: new Date().toISOString(),
            image: image,
            isSelf: true
        });

        // 如果当前正在与该用户聊天，更新显示
        if (currentPrivateChat === targetUser) {
            renderPrivateMessages(newFromUser);
        }
        // else {
        //     // 否则更新私信列表
        //     updatePrivateChatsList();
        // }
    }

    // 处理图片上传
    function handleImageUpload(event) {
        const file = event.target.files[0];
        if (!file) return;

        // 检查文件类型
        if (!file.type.startsWith('image/')) {
            alert('请选择图片文件');
            return;
        }

        // 检查文件大小（限制3MB）
        if (file.size > 3 * 1024 * 1024) {
            alert('图片大小不能超过3MB');
            return;
        }

        selectedImage = file;

        // 显示预览
        const reader = new FileReader();
        reader.onload = function(e) {
            imagePreview.attr('src', e.target.result);
            imagePreviewContainer.removeClass('hidden');

            // 模拟上传进度
            simulateUploadProgress();
        };
        reader.readAsDataURL(file);

        // 重置文件输入，以便可以再次选择同一个文件
        imageUpload.val('');
    }

    // 处理私信图片上传
    function handlePrivateImageUpload(event) {
        const file = event.target.files[0];
        if (!file) return;

        // 检查文件类型
        if (!file.type.startsWith('image/')) {
            alert('请选择图片文件');
            return;
        }

        // 检查文件大小（限制3MB）
        if (file.size > 3 * 1024 * 1024) {
            alert('图片大小不能超过3MB');
            return;
        }

        selectedPrivateImage = file;

        // 压缩并发送图片
        compressImage(file, { maxWidth: 800, maxHeight: 600, quality: 0.7 })
            .then(webpBlob => {
                const reader = new FileReader();
                reader.onload = function(e) {
                    // 发送私信图片
                    sendPrivateMessage(currentPrivateChat, '', e.target.result);
                    // 清除选中状态
                    selectedPrivateImage = null;
                };
                reader.readAsDataURL(webpBlob);
            })
            .catch(error => {
                addSystemMessage(`图片处理失败: ${error.message}`);
            });

        // 重置文件输入
        privateImageUpload.val('');
    }

    // 图片压缩和尺寸调整
    function compressImage(file, options) {
        return new Promise((resolve, reject) => {
            const img = new Image();
            img.onload = function() {
                // 计算压缩后的尺寸（保持比例）
                let width = img.width;
                let height = img.height;

                if (width > options.maxWidth) {
                    height = (height * options.maxWidth) / width;
                    width = options.maxWidth;
                }
                if (height > options.maxHeight) {
                    width = (width * options.maxHeight) / height;
                    height = options.maxHeight;
                }

                // 绘制压缩后的图片
                const canvas = document.createElement('canvas');
                canvas.width = width;
                canvas.height = height;
                const ctx = canvas.getContext('2d');
                ctx.drawImage(img, 0, 0, width, height);

                // 转换为WebP格式
                canvas.toBlob(blob => {
                    if (blob) resolve(blob);
                    else reject(new Error('压缩失败'));
                }, 'image/webp', options.quality);
            };
            img.onerror = () => reject(new Error('图片加载失败'));
            img.src = URL.createObjectURL(file);
        });
    }

    // 模拟上传进度
    function simulateUploadProgress() {
        let progress = 0;
        const interval = setInterval(() => {
            progress += 5;
            uploadProgress.css('width', `${progress}%`);

            if (progress >= 100) {
                clearInterval(interval);
                // 上传完成后隐藏进度条
                setTimeout(() => {
                    uploadProgress.css('width', '0%');
                }, 500);
            }
        }, 100);
    }

    // 移除选中的图片
    function removeSelectedImage() {
        selectedImage = null;
        imagePreview.attr('src', '');
        imagePreviewContainer.addClass('hidden');
        uploadProgress.css('width', '0%');
    }

    // 打开图片查看器
    function openImageViewer(src) {
        viewerImage.attr('src', src);
        imageViewer.addClass('active');
        $('body').addClass('overflow-hidden');
    }

    // 关闭图片查看器
    function closeImageViewer() {
        imageViewer.removeClass('active');
        viewerImage.attr('src', '');
        $('body').removeClass('overflow-hidden');
    }

    // 语音识别功能 - 开始录音
    function startVoiceRecognition(isPrivate = false) {
        // 停止任何正在进行的录音
        if (isRecording) {
            stopVoiceRecognition();
            return;
        }

        // 检查浏览器是否支持语音识别
        if (!('SpeechRecognition' in window || 'webkitSpeechRecognition' in window)) {
            addSystemMessage('抱歉，您的浏览器不支持语音识别功能');
            return;
        }

        // 创建语音识别实例
        const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
        recognition = new SpeechRecognition();

        // 配置识别参数
        recognition.lang = 'zh-CN'; // 设置为中文识别
        recognition.continuous = false; // 只识别一次
        recognition.interimResults = false; // 不返回中间结果
        recognition.maxAlternatives = 1; // 只返回一个最可能的结果

        // 开始录音
        try {
            recognition.start();
            isRecording = true;

            // 更新UI
            if (isPrivate) {
                privateVoiceBtn.find('i').removeClass('text-gray-600').addClass('text-danger voice-recording');
            } else {
                voiceBtn.find('i').removeClass('text-gray-600').addClass('text-danger voice-recording');
            }
            voiceStatus.addClass('active');
            addSystemMessage('开始语音输入...');
        } catch (error) {
            addSystemMessage(`语音识别启动失败: ${error.message}`);
            resetVoiceUI();
        }

        // 识别成功回调
        recognition.onresult = function(event) {
            const transcript = event.results[0][0].transcript;
            // 将识别结果添加到输入框
            if (isPrivate) {
                privateMessageInput.val(privateMessageInput.val() + transcript);
            } else {
                messageInput.val(messageInput.val() + transcript);
            }
            addSystemMessage('语音输入完成');
            resetVoiceUI();
        };

        // 识别结束回调
        recognition.onend = function() {
            if (isRecording) {
                addSystemMessage('语音输入超时');
                resetVoiceUI();
            }
        };

        // 识别错误回调
        recognition.onerror = function(event) {
            let errorMessage = '语音识别出错';
            switch(event.error) {
                case 'not-allowed':
                    errorMessage = '需要麦克风权限才能使用语音输入';
                    break;
                case 'no-speech':
                    errorMessage = '未检测到语音';
                    break;
                case 'audio-capture':
                    errorMessage = '无法访问麦克风';
                    break;
            }
            addSystemMessage(errorMessage);
            resetVoiceUI();
        };
    }

    // 语音识别功能 - 停止录音
    function stopVoiceRecognition() {
        if (recognition && isRecording) {
            recognition.stop();
            isRecording = false;
            resetVoiceUI();
        }
    }

    // 重置语音UI状态
    function resetVoiceUI() {
        isRecording = false;
        voiceBtn.find('i').removeClass('text-danger voice-recording').addClass('text-gray-600');
        privateVoiceBtn.find('i').removeClass('text-danger voice-recording').addClass('text-gray-600');
        voiceStatus.removeClass('active');
    }

    // 添加消息到聊天窗口（支持图片）
    function addMessage(username, message, timestamp, isSelf, image = null) {
        const time = new Date(timestamp).toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});

        // 构建消息内容
        let messageContent = '';
        if (image) {
            // 图片消息
            messageContent = `<img src="${image}" alt="聊天图片" class="message-image" onclick="openImageViewer('${image}')">`;
            // 如果同时有文字内容，一起显示
            if (message) {
                messageContent += `<p class="mt-2">${message}</p>`;
            }
        } else {
            // 文字消息
            messageContent = `<p>${message}</p>`;
        }

        const messageElement = $(`
                <div class="message-appear ${isSelf ? 'flex justify-end mb-4' : 'flex mb-4'}">
                    ${isSelf ? '' : `
                        <div class="mr-2">
                            <img src="https://picsum.photos/id/${(Array.from(username).reduce((acc, char) => acc + char.charCodeAt(0), 0) % 100)}/40/40" alt="${username}" class="w-8 h-8 rounded-full object-cover">
                        </div>
                    `}
                    <div class="${isSelf ? 'text-right' : ''}">
                        ${isSelf ? '' : `<div class="text-xs text-gray-500 mb-1">${username}</div>`}
                        <div class="${isSelf ? 'bg-primary text-white' : 'bg-chatmsg text-gray-800'} rounded-lg p-3 inline-block max-w-[80vw] md:max-w-[24rem]">
                            ${messageContent}
                        </div>
                        <div class="text-xs text-gray-500 mt-1">${time}</div>
                    </div>
                    ${isSelf ? `
                        <div class="ml-2">
                            <img src="https://picsum.photos/id/${(Array.from(username).reduce((acc, char) => acc + char.charCodeAt(0), 0) % 100)}/40/40" alt="${username}" class="w-8 h-8 rounded-full object-cover">
                        </div>
                    ` : ''}
                </div>
            `);

        messageContainer.append(messageElement);
        messageContainer.scrollTop(messageContainer[0].scrollHeight);
    }

    // 添加私信消息
    function addPrivateMessage(fromUser, toUser, message, timestamp, image = null) {
        // 确保私信记录存在
        if (!privateChats[toUser.userid]) {
            privateChats[toUser.userid] = {
                messages: [],
                unread: 0
            };
        }

        // 标记为未读（如果不是当前正在聊天的用户）
        if (currentPrivateChat !== fromUser) {
            privateChats[toUser.userid].unread++;
        }

        // 添加消息
        privateChats[toUser.userid].messages.push({
            fromUser,
            toUser,
            message,
            timestamp,
            image,
            isSelf: fromUser.username === username
        });

        // 更新私信列表
        updatePrivateChatsList("收");

        // 如果当前正在与该用户聊天，更新显示
        if (currentPrivateChat === fromUser) {
            renderPrivateMessages(fromUser);
            // 重置未读计数
            privateChats[toUser.userid].unread = 0;
        } else {
            // 否则显示新消息提示
            addSystemMessage(`收到来自 ${fromUser.username} 的私信`);
        }
    }

    // 渲染私信消息
    function renderPrivateMessages(user) {
        privateMessagesContainer.empty();
        debugger

        if (!privateChats[user.userid] || privateChats[user.userid].messages.length === 0) {
            privateMessagesContainer.append(`
                <div class="text-center text-gray-500 py-8">
                    还没有消息，开始聊天吧！
                </div>
            `);
            return;
        }

        privateChats[user.userid].messages.forEach(msg => {
            const time = new Date(msg.timestamp).toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});

            let messageContent = '';
            if (msg.image) {
                messageContent = `<img src="${msg.image}" alt="私信图片" class="message-image" onclick="openImageViewer('${msg.image}')">`;
                if (msg.message) {
                    messageContent += `<p class="mt-2">${msg.message}</p>`;
                }
            } else {
                messageContent = `<p>${msg.message}</p>`;
            }

            const messageElement = $(`
                <div class="message-appear ${msg.isSelf ? 'flex justify-end mb-4' : 'flex mb-4'}">
                    ${msg.isSelf ? '' : `
                        <div class="mr-2">
                            <img src="https://picsum.photos/id/${(Array.from(msg.fromUser.userid).reduce((acc, char) => acc + char.charCodeAt(0), 0) % 100)}/40/40" alt="${msg.fromUser.username}" class="w-8 h-8 rounded-full object-cover">
                        </div>
                    `}
                    <div class="${msg.isSelf ? 'text-right' : ''}">
                        ${msg.isSelf ? '' : `<div class="text-xs text-gray-500 mb-1">${msg.fromUser.username}</div>`}
                        <div class="${msg.isSelf ? 'bg-primary text-white' : 'bg-private text-gray-800'} rounded-lg p-3 inline-block max-w-[80vw] md:max-w-[24rem]">
                            ${messageContent}
                        </div>
                        <div class="text-xs text-gray-500 mt-1">${time}</div>
                    </div>
                    ${msg.isSelf ? `
                        <div class="ml-2">
                            <img src="https://picsum.photos/id/${(Array.from(username).reduce((acc, char) => acc + char.charCodeAt(0), 0) % 100)}/40/40" alt="${username}" class="w-8 h-8 rounded-full object-cover">
                        </div>
                    ` : ''}
                </div>
            `);

            privateMessagesContainer.append(messageElement);
        });

        privateMessagesContainer.scrollTop(privateMessagesContainer[0].scrollHeight);
    }

    // 更新私信列表
    function updatePrivateChatsList(type) {
        privateChatsList.empty();
        var item = localStorage.getItem("clientId");
        const userids = Object.keys(privateChats);
        if (userids.length === 0) {
            privateChatsList.append(`
                <div class="text-center text-gray-500 py-8">
                    暂无私信，点击在线用户发送私信
                </div>
            `);
            return;
        }
        userids.forEach(userid => {
            const avatarId = Array.from(userid).reduce((acc, char) => acc + char.charCodeAt(0), 0) % 100;
            const hasUnread = privateChats[userid].unread > 0;
            debugger
            if(userid == item){
                const user=  privateChats[userid].messages[0].fromUser;
                const chatItem = $(`
                <div class="private-chat-item ${hasUnread ? 'unread' : ''}" data-user="${userid}">
                    <img src="https://picsum.photos/id/${avatarId}/32/32" alt="${user.username}的头像" class="w-8 h-8 rounded-full object-cover mr-3">
                    <div class="flex-grow">
                        <p class="font-medium text-gray-800">${user.username}</p>
                        <p class="text-xs text-gray-500 truncate">
                            ${privateChats[userid].messages.length > 0
                    ? privateChats[userid].messages[privateChats[userid].messages.length - 1].message || '发送了一张图片'
                    : '开始聊天吧'}
                        </p>
                    </div>
                    ${hasUnread ? `<div class="unread-badge">${privateChats[userid].unread}</div>` : ''}
                </div>
            `);
                privateChatsList.append(chatItem);
            }
        });
    }

    // 添加系统消息
    function addSystemMessage(message) {
        const systemMessage = $(`
                <div class="text-center my-2 message-appear">
                    <span class="bg-gray-200 text-gray-600 text-xs px-3 py-1 rounded-full">${message}</span>
                </div>
            `);

        messageContainer.append(systemMessage);
        messageContainer.scrollTop(messageContainer[0].scrollHeight);
    }

    // 更新用户列表
    function updateUserList(users) {
        usersContainer.empty();
        users.forEach(user => {
            // 跳过自己
            if (user.username === username) return;
            // 为每个用户生成唯一的头像ID
            const avatarId = Array.from(user.userid).reduce((acc, char) => acc + char.charCodeAt(0), 0) % 100;

            const userElement = $(`
                <div class="flex items-center p-2 rounded-lg hover:bg-gray-100 transition-colors duration-200 group">
                    <div class="relative flex-shrink-0">
                        <img
                            src="https://picsum.photos/id/${avatarId}/32/32"
                            alt="${user.username}的头像"
                            class="w-8 h-8 rounded-full object-cover border border-gray-200"
                        >
                        <span class="absolute bottom-0 right-0 w-2.5 h-2.5 bg-success rounded-full border-2 border-white"></span>
                    </div>
                    <div class="ml-3 flex-grow min-w-0">
                        <p class="font-medium text-gray-800 truncate" title="${user.username}">${user.username}</p>
                        <p class="text-xs text-gray-500 mt-0.5">在线</p>
                    </div>
                    <div class="ml-2 opacity-0 group-hover:opacity-100 transition-opacity duration-200">
                        <button
                            class="p-1.5 rounded-full hover:bg-gray-200 transition-colors"
                            title="发送私信"
                            onclick="startPrivateChat('${encodeURIComponent(JSON.stringify(user))}')"
                        >
                            <i class="fa fa-comment-o text-gray-500"></i>
                        </button>
                    </div>
                </div>
            `);
            usersContainer.append(userElement);
        });
    }

    // 开始与指定用户的私信聊天
    function startPrivateChat(userStr) {
        // 解析用户信息
        const user = JSON.parse(decodeURIComponent(userStr));

        currentPrivateChat = user;

        // 更新私信聊天头部信息
        const avatarId = Array.from(user.userid).reduce((acc, char) => acc + char.charCodeAt(0), 0) % 100;
        privateChatAvatar.attr('src', `https://picsum.photos/id/${avatarId}/36/36`);
        privateChatName.text(user.username);

        // 渲染私信消息
        renderPrivateMessages(user);

        // 切换到私信聊天界面
        switchChatTab('private');

        // // 重置未读计数
        // if (privateChats[user]) {
        //     privateChats[user].unread = 0;
        //     updatePrivateChatsList();
        // }

        // 清空私信输入框
        privateMessageInput.val('').focus();
    }

    // 切换聊天标签
    function switchChatTab(tab) {
        if (tab === 'public') {
            publicChatTab.addClass('active');
            privateChatsTab.removeClass('active');
            publicChatContainer.show();
            privateChatsListContainer.hide();
            privateChatContainer.hide();
        } else if (tab === 'privateList') {
            publicChatTab.removeClass('active');
            privateChatsTab.addClass('active');
            publicChatContainer.hide();
            privateChatsListContainer.show();
            privateChatContainer.hide();
            // updatePrivateChatsList();
        } else if (tab === 'private') {
            publicChatContainer.hide();
            privateChatsListContainer.hide();
            privateChatContainer.show();
        }
    }

    // 渲染Emoji列表
    function renderEmojis(container, category = 'all', searchTerm = '') {
        container.empty();

        let emojiList = [];
        if (category === 'all') {
            emojiList = getAllEmojis();
        } else if (emojis[category]) {
            emojiList = emojis[category];
        }

        if (searchTerm) {
            // 简单的表情搜索（实际项目中可根据表情标签进行更精确的搜索）
            emojiList = emojiList.filter(emoji => {
                // 这里仅做示例，实际需实现真实搜索逻辑
                return true;
            });
        }

        const emojiGrid = $('<div class="emoji-grid"></div>');
        emojiList.forEach(emoji => {
            const emojiItem = $(`<div class="emoji-item" title="${emoji}">${emoji}</div>`);
            emojiItem.on('click', () => {
                // 确定是公共聊天还是私信的表情选择器
                const isPrivate = container.attr('id') === 'privateEmojiContent';
                const input = isPrivate ? privateMessageInput[0] : messageInput[0];

                const cursorPos = input.selectionStart;
                const currentValue = input.value;

                // 插入表情
                const newValue = currentValue.substring(0, cursorPos) + emoji + currentValue.substring(cursorPos);

                if (isPrivate) {
                    privateMessageInput.val(newValue);
                } else {
                    messageInput.val(newValue);
                }

                // 更新光标位置
                const newCursorPos = cursorPos + emoji.length;
                input.focus();
                input.setSelectionRange(newCursorPos, newCursorPos);
            });
            emojiGrid.append(emojiItem);
        });

        container.append(emojiGrid);
    }

    // 切换用户列表显示/隐藏
    function toggleUserList() {
        if (userList.hasClass('hidden') || userList.hasClass('-translate-x-full')) {
            // 显示用户列表
            userList.removeClass('hidden');
            setTimeout(() => {
                userList.removeClass('-translate-x-full');
            }, 10);

            // 在移动设备上显示遮罩层
            if (window.innerWidth < 768) {
                userListOverlay.removeClass('hidden');
                $('body').addClass('overflow-hidden'); // 防止背景滚动
            }
        } else {
            // 隐藏用户列表
            userList.addClass('-translate-x-full');
            setTimeout(() => {
                userList.addClass('hidden');
            }, 300);

            userListOverlay.addClass('hidden');
            $('body').removeClass('overflow-hidden');
        }
    }

    // 处理分片消息
    function handleChunkedMessage(data) {
        // 实现分片消息处理逻辑
        console.log('处理分片消息:', data);
        // 这里应该有与后端对应的分片处理逻辑
    }

    // 页面可见性变化事件监听
    document.addEventListener('visibilitychange', () => {
        if (document.visibilityState === 'visible') {
            resetUnreadMessageCount();

            // 检查连接状态，必要时尝试重连
            if (!ws || ws.readyState !== WebSocket.OPEN) {
                const url = wsUrl.val().trim();
                if (url) {
                    addSystemMessage('页面已激活，正在检查连接...');
                    connectWebSocket(url);
                }
            }
        }
    });

    // 事件绑定
    $(document).ready(function() {
        const url=document.URL.split(":")[1];
        $("#wsUrl").val("wss:"+url+"websocket");
        // 初始化登录时间显示
        const date = new Date();
        const hours = String(date.getHours()).padStart(2, '0');
        const minutes = String(date.getMinutes()).padStart(2, '0');
        $("#loginTime").text(`${hours}:${minutes}`);

        // 检查本地存储的客户端ID
        let clientId = localStorage.getItem("clientId");
        if(!clientId){
            // 生成新的客户端ID
            clientId = generateUUID();
            localStorage.setItem("clientId", clientId);
            // 显示连接设置
            showConnectionModal();
        } else {
            // 从本地存储获取用户名
            const storedUsername = localStorage.getItem(clientId);
            if (storedUsername) {
                username = storedUsername;
                $("#username").val(username);
            }
            // 尝试连接
            const url = wsUrl.val().trim();
            if (url) connectWebSocket(url);
        }

        // 初始化渲染所有表情
        renderEmojis(emojiContent);
        renderEmojis(privateEmojiContent);

        // 连接按钮点击事件
        connectBtn.on('click', function() {
            const url = wsUrl.val().trim();
            if (!url) {
                alert('请输入WebSocket地址');
                return;
            }
            username = usernameInput.val().trim() || '游客';
            // 保存用户名到本地存储
            localStorage.setItem(clientId, username);
            connectWebSocket(url);
        });

        // 关闭模态框按钮点击事件
        closeModal.on('click', hideConnectionModal);

        // 发送消息按钮点击事件
        sendBtn.on('click', function() {
            const message = messageInput.val().trim();

            // 检查是否有图片或消息内容
            if (!message && !selectedImage) {
                return; // 什么都没有，不发送
            }

            // 准备发送的数据
            const data = {
                type: 'message',
                username: username,
                message: message,
                timestamp: new Date().toISOString(),
                image: null
            };

            // 如果有选中的图片，转换为Base64并压缩
            if (selectedImage) {
                compressImage(selectedImage, { maxWidth: 800, maxHeight: 600, quality: 0.7 })
                    .then(webpBlob => {
                        const reader = new FileReader();
                        reader.onload = function(e) {
                            data.image = e.target.result;

                            // 发送消息
                            sendMessage(data);

                            // 添加自己发送的消息
                            addMessage(username, message, new Date().toISOString(), true, data.image);

                            // 清空输入和图片
                            messageInput.val('').focus();
                            removeSelectedImage();
                        };
                        reader.readAsDataURL(webpBlob);
                    })
                    .catch(error => {
                        addSystemMessage(`图片处理失败: ${error.message}`);
                    });
            } else {
                // 只发送文字消息
                sendMessage(data);

                // 添加自己发送的消息
                addMessage(username, message, new Date().toISOString(), true);

                // 清空输入框
                messageInput.val('').focus();
            }
        });

        // 发送私信按钮点击事件
        privateSendBtn.on('click', function() {
            if (!currentPrivateChat) return;

            const message = privateMessageInput.val().trim();
            // 发送私信
            sendPrivateMessage(currentPrivateChat, message);

            // 清空输入框
            privateMessageInput.val('').focus();
        });

        // 输入框回车发送消息
        messageInput.on('keypress', function(e) {
            if (e.which === 13 && !e.shiftKey) { // Enter键且未按Shift
                e.preventDefault();
                sendBtn.click();
            }
        });

        // 私信输入框回车发送
        privateMessageInput.on('keypress', function(e) {
            if (e.which === 13 && !e.shiftKey) { // Enter键且未按Shift
                e.preventDefault();
                privateSendBtn.click();
            }
        });

        // 设置按钮点击事件
        $('#settingsBtn').on('click', function() {
            if (ws && ws.readyState === WebSocket.OPEN) {
                is主动关闭 = true;
                ws.close(1000, '用户主动断开');
                addSystemMessage('已断开连接，请重新配置连接');
            }
            showConnectionModal();
        });

        // 切换用户列表按钮点击事件
        toggleUsers.on('click', toggleUserList);

        // 用户列表遮罩层点击事件
        userListOverlay.on('click', toggleUserList);

        // 主题切换按钮点击事件
        $('#themeToggle').on('click', function() {
            const icon = $(this).find('i');
            if (icon.hasClass('fa-moon-o')) {
                icon.removeClass('fa-moon-o').addClass('fa-sun-o');
                // 暗色主题切换逻辑
                $('body').addClass('dark-mode');
            } else {
                icon.removeClass('fa-sun-o').addClass('fa-moon-o');
                // 亮色主题切换逻辑
                $('body').removeClass('dark-mode');
            }
        });

        // 切换聊天标签
        publicChatTab.on('click', () => switchChatTab('public'));
        privateChatsTab.on('click', () => switchChatTab('privateList'));

        // 返回私信列表
        backToPrivateList.on('click', () => switchChatTab('privateList'));

        // 点击私信列表项开始聊天
        privateChatsList.on('click', '.private-chat-item', function() {
            const user = $(this).data('user');
            startPrivateChat(user);
        });

        // 切换Emoji选择器显示/隐藏
        toggleEmojiPicker.on('click', function(e) {
            e.stopPropagation();
            emojiPicker.toggleClass('active');
            privateEmojiPicker.removeClass('active');
        });

        // 切换私信Emoji选择器显示/隐藏
        togglePrivateEmojiPicker.on('click', function(e) {
            e.stopPropagation();
            privateEmojiPicker.toggleClass('active');
            emojiPicker.removeClass('active');
        });

        // Emoji分类切换
        $('.emoji-tab').on('click', function(e) {
            e.stopPropagation();
            const category = $(this).data('category');
            const isPrivate = $(this).closest('#privateEmojiPicker').length > 0;

            $(this).closest('.emoji-tabs').find('.emoji-tab').removeClass('active');
            $(this).addClass('active');

            if (isPrivate) {
                renderEmojis(privateEmojiContent, category, privateEmojiSearch.val());
            } else {
                renderEmojis(emojiContent, category, emojiSearch.val());
            }
        });

        // Emoji搜索
        emojiSearch.on('input', function() {
            const activeCategory = $('#emojiPicker .emoji-tab.active').data('category');
            renderEmojis(emojiContent, activeCategory, $(this).val());
        });

        // 私信Emoji搜索
        privateEmojiSearch.on('input', function() {
            const activeCategory = $('#privateEmojiPicker .emoji-tab.active').data('category');
            renderEmojis(privateEmojiContent, activeCategory, $(this).val());
        });

        // 点击Emoji选择器内部不关闭选择器
        $('.emoji-picker').on('click', function(e) {
            e.stopPropagation();
        });

        // 点击页面其他地方关闭Emoji选择器
        $(document).on('click', function() {
            emojiPicker.removeClass('active');
            privateEmojiPicker.removeClass('active');
        });

        // 图片上传事件
        imageUpload.on('change', handleImageUpload);

        // 私信图片上传事件
        privateImageUpload.on('change', handlePrivateImageUpload);

        // 移除图片事件
        removeImage.on('click', removeSelectedImage);

        // 关闭图片查看器事件
        closeViewer.on('click', closeImageViewer);

        // 点击图片查看器背景关闭
        imageViewer.on('click', function(e) {
            if (e.target === imageViewer[0]) {
                closeImageViewer();
            }
        });

        // 语音按钮点击事件
        voiceBtn.on('click', () => startVoiceRecognition(false));

        // 私信语音按钮点击事件
        privateVoiceBtn.on('click', () => startVoiceRecognition(true));

        // 窗口大小变化时处理用户列表显示
        $(window).on('resize', function() {
            if (window.innerWidth >= 768 && userList.hasClass('hidden')) {
                userList.removeClass('hidden -translate-x-full');
                userListOverlay.addClass('hidden');
                $('body').removeClass('overflow-hidden');
            } else if (window.innerWidth < 768 && !userList.hasClass('hidden') && !userList.hasClass('-translate-x-full')) {
                userListOverlay.removeClass('hidden');
            }
        });

        // 窗口关闭时处理连接
        window.addEventListener('beforeunload', function() {
            if (ws && ws.readyState === WebSocket.OPEN) {
                is主动关闭 = true;
                sendMessage({
                    type: 'leave',
                    username: username,
                    timestamp: new Date().toISOString()
                });
                ws.close(1001, '页面关闭');
            }
        });
    });
</script>
</body>
</html>
